/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
*/

package com.jinhe.tss.core.cachepool.extend.thread;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import com.jinhe.tss.core.cachepool.Cacheable;
import com.jinhe.tss.core.cachepool.IPool;
import com.jinhe.tss.core.cachepool.ReusablePool;
import com.jinhe.tss.core.cachepool.TimeWrapper;
import com.jinhe.tss.core.cachepool.extend.assignment.IAssignment;

/** 
 * <p> ThreadPool.java </p> 
 * 
 * <p></p>
 * 采用缓存池机制实现的线程池（区别于ThreadPool_old:池由一个数组简单实现）。<p></p>
 * 通过继承ReusablePool父类，使得ThreadPool自身也成为了一个缓存池，<p></p>
 * 每次运行excute()方法，都会唤醒free池中的工作线程。<p></p>
 * 
 * 对池中的所有线程来说，它们都共享池的工作队列。</p><p>
 * 所以工作队列要求能实现同步，通过Collections.synchronizedList(new LinkedList())实现。</p><p>
 * 如果队列不为空的话，那么线程将反复的执行，来完成工作队列中的每个工作，直到工作队列为空。</p><p>
 * 
 * @author Jon.King 2007-1-9
 */
public class ThreadPool extends ReusablePool implements IThreadPool{  
    
    private IPool taskPool;

    private final List<Cacheable> workQueue ;

    public ThreadPool() {
        workQueue = Collections.synchronizedList(new LinkedList<Cacheable>());
    }
    
    public void excute(IAssignment task) {
        excute(null, new TimeWrapper(task, task));
    }

    public void excute(IPool taskPool, Cacheable task) {
        this.taskPool = taskPool;
        
        //如果池中工作线程都已被销毁，则重新开始初始化。 （单单size()=0，有可能正在初始化）
        if(getSize() == 0 && released){
            super.flush();
            super.init();
        }
        
        log.debug("ThreadPool.excute: 【" + task.getValue() + "】");
        synchronized (workQueue) {
            workQueue.add(task);
            workQueue.notifyAll();  // workQueue在ThreadPoolWorker.run方法里wait()
        }
    }
    
    public Thread createWorkThread(){
        return new ThreadPoolWorker(TimeWrapper.createRandomKey("WorkThread"));
    }
    
    class ThreadPoolWorker extends Thread {
        
        public ThreadPoolWorker(String name){
            super(name);
        }
        
        public void run() {
            Cacheable taskWrapper;
            while (true) {
                synchronized (workQueue) {
                    while (workQueue.isEmpty()) {
                        try {
                            workQueue.wait(); //当前工作线程（this）进入等待状态
                            //（线程进入workQueue对象的休息室waitSet，需要由workQueue对象唤醒，see Object.wait()方法）
                        } catch (InterruptedException ignored) {
                        }
                    }
                    taskWrapper = (Cacheable) workQueue.remove(0); //将任务从队列中移除
                }
                
                // 执行任务队列中的任务，由ThreadPool中的一个Worker来执行
                try {
                    if (taskWrapper != null) {
                        IAssignment task = (IAssignment) taskWrapper.getValue();
                        log.debug( this + ".run : 【" + task + "】");
                        task.excute(); //执行任务
                        
                        if(taskPool != null){
                            log.debug("空闲项 = 【" + taskPool.getFree().size() + "】个");
                            log.debug(taskPool.getUsing());
                            taskPool.checkIn(taskWrapper);
                        }
                        //设置池、缓存项的命中率
                        ThreadPool.this.addRequests(); //如此可以引用到外围类的实例
                        ThreadPool.this.addHits();
                        ThreadPool.this.getFree().get(super.getName()).addHit();
                    }
                } catch (RuntimeException e) {
                    log.error("ThreadPoolWorker执行任务时候出错", e);
                } 
            }
        }
        
        public String toString(){
            return super.getName();
        }
    }
}

